home *** CD-ROM | disk | FTP | other *** search
/ Delphi 2 - Developers' Solutions / Delphi 2 Developers' Solutions.iso / dds / chap06 / howto03 / dibfiles.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1996-01-04  |  18.0 KB  |  488 lines

  1. {==========================================================================}
  2. {                       UNIT --> DIBFILES <--                              }
  3. {                                                                          }
  4. { This unit is designed to handle the loading and drawing of device-       }
  5. { independent bitmap files in Windows 3.0. (FBMPMGR handles the interface  }
  6. { to hyperspace applications.)  This unit does the grunt work, via the     }
  7. { File_Bitmap object.                                                      }
  8. {==========================================================================}
  9.  
  10. unit dibfiles;
  11.  
  12. {**************************************************************************}
  13. {                                                                          }
  14. {                            INTERFACE SECTION                             }
  15. {                                                                          }
  16. {**************************************************************************}
  17.  
  18. interface
  19.  
  20. {**************************************************************************}
  21. {                                                                          }
  22. {                                USES SECTION                              }
  23. {                                                                          }
  24. {**************************************************************************}
  25.  
  26. uses
  27.  
  28. Strings,             { Windows 3.x Strings Unit                         }
  29. WinAPI,              { Windows 3.x API Unit                             }
  30. WinCrt,              { Windows 3.x Crt Unit                             }
  31. WinPrn,              { Windows 3.x Printer Unit                         }
  32. WinProcs,            { Windows 3.x Standard Procedures Unit             }
  33. WinTypes,            { Windows 3.x Types Unit                           }
  34. OWindows,            { Windows 3.x Windows Unit                         }
  35. ODialogs,            { Windows 3.x Dialogs Unit                         }
  36. OMemory,             { Windows 3.x Memory Management Unit               }
  37. Objects,             { Windows 3.x Object Management Unit               }
  38. OPrinter,            { Windows 3.x Printer Management Unit              }
  39. OStdDlgs,            { Windows 3.x Standard Dialog Unit                 }
  40. OStdWnds,            { Windows 3.x Standard Windows Unit                }
  41. Validate;            { Windows 3.x Validation Unit                      }
  42.  
  43. {**************************************************************************}
  44. {                                                                          }
  45. {                              TYPES SECTION                               }
  46. {                                                                          }
  47. {**************************************************************************}
  48.  
  49. type
  50.  
  51. {++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  52. { FILE_BITMAP Object                                                       }
  53. {                                                                          }
  54. { This object handles the loading and drawing of DIB files in Windows 3.0  }
  55. { If a file cannot be found or is not a 3.0 DIB error codes are returned.  }
  56. {++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  57.  
  58. PFile_Bitmap = ^File_Bitmap;
  59. File_BitMap = object( TObject )
  60.  
  61. Bitmap_Handle    : HBitmap;   { Holds the DIB when done               }
  62. Width            : Longint;   { Holds the pixel width when done       }
  63. Height           : Longint;   { Holds the pixel height when done      }
  64. The_File         : File;      { File variable for internal use        }
  65. The_Name         : PChar;     { Holds the file name                   }
  66. Bits_Handle      : THandle;   { temporary holder for the DIB          }
  67. Bits_Byte_Size   : Longint;   { temporary holder for the              }
  68.                               { byte length of the DIB                }
  69. Error_Status     : Integer;   { code for error condition on the DIB   }
  70.  
  71. constructor INIT( The_DIB_Name : PChar );
  72. destructor DONE; virtual;
  73. procedure GET_BITMAP_DATA;
  74. function GET_BITMAP : HBitmap;
  75. function GET_BITMAP_NAME : PChar;
  76. function LOAD_BITMAP_FILE : Boolean;
  77. function OPEN_DIB : Boolean;
  78. function GET_ERROR_STATUS : Integer;
  79. function GET_FILE_NAME : PChar;
  80. procedure DRAW( The_DC       : HDC;
  81.                 X_Location ,
  82.                 Y_Location   : Integer );
  83. procedure DRAW_RESIZED( The_DC               : HDC;
  84.                         X_Location         ,
  85.                         Y_Location         ,
  86.                         Destination_Width ,
  87.                         Destination_Height    : integer );
  88. procedure GET_DIB_DIMENSIONS( var The_Width  ,
  89.                                   The_Height   : Longint );
  90.  
  91. end;
  92. {**************************************************************************}
  93. {                                                                          }
  94. {                        IMPLEMENTATION SECTION                            }
  95. {                                                                          }
  96. {**************************************************************************}
  97.  
  98. implementation
  99.  
  100. {--------------------------------------------------------------------------}
  101. {  _AHINCR Function                                                        }
  102. {                                                                          }
  103. {  This is a "magic" function; defining it causes 3.0 to patch the value   }
  104. {  into the passed reference.  This makes it a peculiar type of global     }
  105. {  variable. To use the value of AHINCR, use OFS( AHINCR ).                }
  106. {--------------------------------------------------------------------------}
  107.  
  108. procedure AHIncr; FAR; EXTERNAL 'KERNEL' INDEX 114;
  109.  
  110. {--------------------------------------------------------------------------}
  111. { INIT Method                                                              }
  112. {                                                                          }
  113. { This method initializes the DIB by setting the handle to 0, storing the  }
  114. { input filename, and calling the LOAD_BITMAP_FILE method.                 }
  115. {--------------------------------------------------------------------------}
  116.  
  117. constructor File_Bitmap.INIT( The_DIB_Name : PChar );
  118.  
  119. begin
  120.  
  121. Bitmap_Handle := 0;
  122. The_Name := The_DIB_Name;
  123. LOAD_BITMAP_FILE;
  124.  
  125. end;
  126.  
  127. {--------------------------------------------------------------------------}
  128. { DONE Method                                                              }
  129. {                                                                          }
  130. { This method deallocates any memory given to the DIB.                     }
  131. {--------------------------------------------------------------------------}
  132.  
  133. destructor File_Bitmap.DONE;
  134.  
  135. begin
  136.  
  137. if Bitmap_Handle <> 0 then DELETEOBJECT( Bitmap_Handle );
  138.  
  139. end;
  140.  
  141. {--------------------------------------------------------------------------}
  142. { GET_BITMAP_DATA Method                                                   }
  143. {                                                                          }
  144. { This method copies the bitmap bits data from the file into memory. Since }
  145. { copying cannot cross a segment (64K) boundary, segment arithmetic must   }
  146. { be done on the fly.  A LongType type was created to simplify this process}
  147. {--------------------------------------------------------------------------}
  148.  
  149. procedure File_Bitmap.GET_BITMAP_DATA;
  150.  
  151. type
  152.  
  153. LongType = record
  154.  
  155. case Word of
  156. 0: ( Ptr  : Pointer );
  157. 1: ( Long : Longint );
  158. 2: ( Lo   : Word;
  159. Hi   : Word    );
  160.  
  161. end;
  162.  
  163. var
  164.  
  165. Count   : Longint;
  166. Start,
  167. ToAddr,
  168. Bits    : LongType;
  169. begin
  170.  
  171. Start.Long := 0;
  172. Bits.Ptr := GLOBALLOCK( Bits_Handle );
  173. Count := Bits_Byte_Size - Start.Long;
  174. while Count > 0 do
  175. begin
  176. ToAddr.Hi := Bits.Hi + ( Start.Hi * OFS( AHIncr ));
  177. ToAddr.Lo := Start.Lo;
  178. if Count > $4000 then Count := $4000;
  179. BLOCKREAD( The_File , ToAddr.Ptr^ , Count );
  180. Start.Long := Start.Long + Count;
  181. Count := Bits_Byte_Size - Start.Long;
  182. end;
  183. GLOBALUNLOCK( Bits_Handle );
  184. end;
  185.  
  186. {--------------------------------------------------------------------------}
  187. { LOAD_BITMAP_FILE Method                                                  }
  188. {                                                                          }
  189. { This method is called to actually load the DIB into Windows 3.0. It sets }
  190. { Error_status 0 if no problems, -1 if no file found, and -2 if not a DIB. }
  191. {--------------------------------------------------------------------------}
  192.  
  193. function File_Bitmap.LOAD_BITMAP_FILE : Boolean;
  194. var
  195. Test_Win30_Bitmap : Longint;
  196. Memory_DC         : HDC;
  197. The_IO_Result     : Word;
  198. begin
  199. Error_Status := 0;
  200. LOAD_BITMAP_FILE := false;
  201. ASSIGN( The_File , The_Name );
  202. {$I-}
  203. RESET( The_File , 1 );
  204. SEEK( The_File , 14 );
  205. BLOCKREAD( The_File , Test_Win30_Bitmap , SIZEOF( Test_Win30_Bitmap ));
  206. {$I+}
  207. The_IO_Result := IOResult;
  208. If The_IO_Result <> 0 then
  209. begin
  210. Error_Status := -1;
  211. The_Global_Error_Code := The_IO_Result;
  212. end
  213. else
  214. begin
  215. if Test_Win30_Bitmap = 40 then
  216. begin
  217. if OPEN_DIB then
  218. begin
  219. LOAD_BITMAP_FILE := true;
  220. end;
  221. end
  222. else Error_Status := -2;
  223. CLOSE( The_File );
  224. end;
  225.  
  226. end;
  227.  
  228. {--------------------------------------------------------------------------}
  229. { OPEN_DIB Method                                                          }
  230. {                                                                          }
  231. { This method does the grunt work of decoding the DIB file and obtaining   }
  232. { a bitmap handle from memory and storing the bitmap in it. If the format  }
  233. { is incorrect (more than 8 bits per color value) error code -3 is set; if }
  234. { memory is not available for the DIB error code -4 is set.                }
  235. {--------------------------------------------------------------------------}
  236.  
  237. function File_Bitmap.OPEN_DIB : Boolean;
  238.  
  239. var
  240.  
  241. Bit_Count         : Word;
  242. Size              : Word;
  243. Long_Width        : Longint;
  244. DC_Handle         : HDC;
  245. Bits_Ptr          : Pointer;
  246. Bitmap_Info       : PBitmapInfo;
  247. New_Bitmap_Handle : THandle;
  248. New_Pixel_Width,
  249. New_Pixel_Height  : Word;
  250.  
  251. begin
  252.  
  253. OPEN_DIB := true;
  254. SEEK( The_File , 28 );
  255. BLOCKREAD( The_File , Bit_Count , SIZEOF( Bit_Count ));
  256. if Bit_Count <= 8 then
  257. begin
  258. Size := SIZEOF( TBitmapInfoHeader ) + (( 1 SHL Bit_Count )
  259. * SIZEOF( TRGBQuad ));
  260. Bitmap_Info := MEMALLOC( Size );
  261. SEEK( The_File , SIZEOF( TBitmapFileHeader ));
  262. BLOCKREAD( The_File , Bitmap_Info^ , Size );
  263. New_Pixel_Width := Bitmap_Info^.bmiHeader.biWidth;
  264. New_Pixel_Height := Bitmap_Info^.bmiHeader.biHeight;
  265. Long_Width := ((( New_Pixel_Width * Bit_Count ) + 31 ) div 32 ) * 4;
  266. Bitmap_Info^.bmiHeader.biSizeImage := Long_Width * New_Pixel_Height;
  267. GLOBALCOMPACT( -1 );
  268. Bits_Handle := GLOBALALLOC( gmem_Moveable or gmem_Zeroinit ,
  269. Bitmap_Info^.bmiHeader.biSizeImage );
  270. Bits_Byte_Size := Bitmap_Info^.bmiHeader.biSizeImage;
  271. GET_BITMAP_DATA;
  272. DC_Handle := CREATEDC( 'Display' , nil , nil , nil );
  273. Bits_Ptr := GLOBALLOCK( Bits_Handle );
  274. New_Bitmap_Handle :=
  275. CREATEDIBITMAP( DC_Handle , Bitmap_Info^.bmiHeader ,
  276. cbm_Init , Bits_Ptr , Bitmap_Info^ , 0 );
  277. DELETEDC( DC_Handle );
  278. GLOBALUNLOCK( Bits_Handle );
  279. GLOBALFREE( Bits_Handle );
  280. FREEMEM( Bitmap_Info , Size );
  281. if New_Bitmap_Handle <> 0 then
  282. begin
  283. if Bitmap_Handle <> 0 then DELETEOBJECT( Bitmap_Handle );
  284. Bitmap_Handle := New_Bitmap_Handle;
  285. Width := New_Pixel_Width;
  286. Height := New_Pixel_Height;
  287. end
  288. else
  289. begin
  290. OPEN_DIB := false;
  291. Error_Status := -4;
  292. end;
  293. end
  294. else
  295. begin
  296. OPEN_DIB := false;
  297. Error_Status := -3;
  298. end;
  299.  
  300. end;
  301.  
  302. {--------------------------------------------------------------------------}
  303. { GET_ERROR_STATUS Method                                                  }
  304. {                                                                          }
  305. { This function returns the value of the Error_Status flag; it will be     }
  306. { called by higher-level routines to check if INIT or CHANGE was successful}
  307. {--------------------------------------------------------------------------}
  308.  
  309. function File_Bitmap.GET_ERROR_STATUS : Integer;
  310.  
  311. begin
  312.  
  313. GET_ERROR_STATUS := Error_Status;
  314.  
  315. end;
  316.  
  317. {--------------------------------------------------------------------------}
  318. { GET_FILE_NAME Method                                                     }
  319. {                                                                          }
  320. { This function returns the current name and path of the DIB file. It is   }
  321. { used for error checking to verify the correct path has been used.        }
  322. {--------------------------------------------------------------------------}
  323.  
  324. function File_Bitmap.GET_FILE_NAME : PChar;
  325.  
  326. begin
  327.  
  328. GET_FILE_NAME := The_Name;
  329.  
  330. end;
  331.  
  332. {--------------------------------------------------------------------------}
  333. { GET_DIB_DIMENSIONS Method                                                }
  334. {                                                                          }
  335. { This procedure is used to obtain the pixel dimensions of the DIB; it is  }
  336. { used by higher-level constructs to correctly size themselves.            }
  337. {--------------------------------------------------------------------------}
  338.  
  339. procedure File_Bitmap.GET_DIB_DIMENSIONS( var The_Width ,
  340. The_Height  : Longint );
  341.  
  342. begin
  343.  
  344. The_Width := Width;
  345. The_Height := Height;
  346.  
  347. end;
  348.  
  349. {--------------------------------------------------------------------------}
  350. { DRAW Method                                                              }
  351. {                                                                          }
  352. { This method handles the grunt level work of drawing the DIB in the DC at }
  353. { the specified coordinates. If the bitmap handle is zero it reloads DIB.  }
  354. {--------------------------------------------------------------------------}
  355.  
  356. procedure File_Bitmap.DRAW( The_DC      : HDC;
  357. X_Location,
  358. Y_Location  : integer );
  359.  
  360. var
  361.  
  362. Memory_DC : HDC;
  363.  
  364. begin
  365.  
  366. if Bitmap_Handle <> 0 then
  367. begin
  368. Memory_DC := CREATECOMPATIBLEDC( The_DC );
  369. SELECTOBJECT( Memory_DC , Bitmap_Handle );
  370. BITBLT( The_DC , X_Location , Y_Location , Width ,
  371. Height , Memory_DC , 0 , 0 , SRCCopy );
  372. DELETEDC( Memory_DC );
  373. end
  374. else
  375. begin
  376. if LOAD_BITMAP_FILE then
  377. begin
  378. Memory_DC := CREATECOMPATIBLEDC( The_DC );
  379. SELECTOBJECT( Memory_DC , Bitmap_Handle );
  380. BITBLT( The_DC , X_Location , Y_Location , Width ,
  381. Height , Memory_DC , 0 , 0 , SRCCopy );
  382. DELETEDC( Memory_DC );
  383. end;
  384. end;
  385.  
  386. end;
  387.  
  388. {--------------------------------------------------------------------------}
  389. { DRAW_RESIZED Method                                                      }
  390. {                                                                          }
  391. { This method handles the grunt level work of drawing the DIB in the DC at }
  392. { the specified coordinates. If the bitmap handle is zero it reloads DIB.  }
  393. { It takes two extra parameters, Destination_Width and Destination_Height  }
  394. { which determine the final size of the drawn bitmap.                      }
  395. {--------------------------------------------------------------------------}
  396. procedure File_Bitmap.DRAW_RESIZED( The_DC               : HDC;
  397. X_Location         ,
  398. Y_Location         ,
  399. Destination_Width ,
  400. Destination_Height    : integer );
  401.  
  402. var
  403.  
  404. Memory_DC : HDC;
  405.  
  406. begin
  407.  
  408. if Bitmap_Handle <> 0 then
  409. begin
  410. Memory_DC := CREATECOMPATIBLEDC( The_DC );
  411. SELECTOBJECT( Memory_DC , Bitmap_Handle );
  412. SETSTRETCHBLTMODE( The_DC , {STRETCH_DELETESCANS} 3 );
  413. STRETCHBLT( The_DC             ,
  414. X_Location         ,
  415. Y_Location         ,
  416. Destination_Width  ,
  417. Destination_Height ,
  418. Memory_DC          ,
  419. 0                  ,
  420. 0                  ,
  421. Width              ,
  422. Height             ,
  423. SRCCopy              );
  424. DELETEDC( Memory_DC );
  425. end
  426. else
  427. begin
  428. if LOAD_BITMAP_FILE then
  429. begin
  430. Memory_DC := CREATECOMPATIBLEDC( The_DC );
  431. SELECTOBJECT( Memory_DC , Bitmap_Handle );
  432. SETSTRETCHBLTMODE( The_DC , {STRETCH_DELETESCANS} 3 );
  433. STRETCHBLT( The_DC             ,
  434. X_Location         ,
  435. Y_Location         ,
  436. Destination_Width  ,
  437. Destination_Height ,
  438. Memory_DC          ,
  439. 0                  ,
  440. 0                  ,
  441. Width              ,
  442. Height             ,
  443. SRCCopy              );
  444. DELETEDC( Memory_DC );
  445. end;
  446. end;
  447. end;
  448.  
  449. {--------------------------------------------------------------------------}
  450. { GET_BITMAP Method                                                        }
  451. {                                                                          }
  452. { This method obtains a bitmap for the DIB from the Bitmap_handle field.   }
  453. { It is used by higher-level constructs for obscure purposes.              }
  454. {--------------------------------------------------------------------------}
  455. function File_Bitmap.GET_BITMAP : HBitmap;
  456. begin
  457. if Bitmap_Handle = 0 then
  458. begin
  459. if LOAD_BITMAP_FILE then
  460. GET_BITMAP := Bitmap_Handle
  461. else GET_BITMAP := 0;
  462. end
  463. else GET_BITMAP := Bitmap_Handle;
  464. end;
  465.  
  466. {--------------------------------------------------------------------------}
  467. { GET_BITMAP_NAME Method                                                   }
  468. {                                                                          }
  469. { This method obtains a DIB's filename and path from the The_Name field.   }
  470. { It is used by higher-level constructs for obscure purposes.              }
  471. {--------------------------------------------------------------------------}
  472. function File_Bitmap.GET_BITMAP_NAME : PChar;
  473. begin
  474. GET_BITMAP_NAME := The_Name;
  475. end;
  476. {**************************************************************************}
  477. {                                                                          }
  478. {                           INITIALIZATION SECTION                         }
  479. {                                                                          }
  480. {**************************************************************************}
  481.  
  482. {<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><}
  483. {                                                                         }
  484. {  No initialization section for this unit.                               }
  485. {                                                                         }
  486. {<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><}
  487. end.
  488.